﻿using System;
using System.Linq;
using System.Collections.Generic;
using Xoohoo.Infrastructure;
using Xoohoo.Extensions;
using Xoohoo.Models;
using Xoohoo.Models.InputModels;
using Xoohoo.Repositories;

namespace Xoohoo.Services
{
    public class PermissionService : IPermissionService
    {
        private readonly IPermissionRepository _repository;
        private readonly ICacheModule _cache;
        private readonly string _permissionListCacheKey = "PermissionList";

        public PermissionService(IPermissionRepository repository, IModuleRegistry modules)
        {
            this._repository = repository;
            this._cache = modules.GetModules<ICacheModule>().Last();
        }

        #region IPermissionService Members

        public Permission GetItem(string permissionName)
        {
            List<Permission> permissions = GetListFromCache();
            if (!permissions.IsNullOrEmpty())
                return permissions.FirstOrDefault(m => m.PermissionName == permissionName);
            else
                return _repository.GetItem(permissionName);
        }

        public Permission GetItem(Guid permissionID)
        {
            List<Permission> permissions = GetListFromCache();
            if (!permissions.IsNullOrEmpty())
                return permissions.FirstOrDefault(m => m.PermissionID == permissionID);
            else
                return _repository.GetItem(permissionID);
        }

        public List<Permission> GetList()
        {
            List<Permission> permissions = GetListFromCache();
            if (!permissions.IsNullOrEmpty())
                return ClonePermissions(permissions);
            else
                return _repository.GetList();
        }

        public ModelResult Save(PermissionInput permissionInput)
        {
            if (permissionInput == null)
                throw new ArgumentNullException("permissionInput");

            _repository.Save(permissionInput);
            _cache.Invalidate(_permissionListCacheKey);
            return ModelResult.Empty;
        }

        public ModelResult Save(IEnumerable<PermissionInput> permissions)
        {
            ModelResult modelResult = new ModelResult();
            if (permissions == null) return modelResult; 

            foreach (var per in permissions)
                _repository.Save(per);

            _cache.Invalidate(_permissionListCacheKey);
            return modelResult;
        }

        public bool Remove(Guid permissionID)
        {
            bool result = _repository.Remove(permissionID);
            if (result)
                _cache.Invalidate(_permissionListCacheKey);
            return result;
        }

        public bool Remove(IEnumerable<Guid> iDs)
        {
            bool result = true;
            if (iDs == null) return result;

            foreach (var id in iDs)
                result = _repository.Remove(id);

            if (result)
                _cache.Invalidate(_permissionListCacheKey);
            return result;
        }

        public bool Move(Guid permissionID, MovingTarget target)
        {
            bool result = _repository.Move(permissionID, target);
            if (result)
                _cache.Invalidate(_permissionListCacheKey);
            return result;
        }

        #endregion

        #region Private Methods

        private List<Permission> ClonePermissions(IEnumerable<Permission> source)
        {
            if (source.IsNullOrEmpty())
                return new List<Permission>();

            //深度克隆
            return (source.DeepClone() as IEnumerable<Permission>).ToList();
        }

        private List<Permission> GetListFromCache()
        {
            if (_cache != null)
                return _cache.GetItem<List<Permission>>(
                    _permissionListCacheKey, () => _repository.GetList(),
                    null
                    );
            else
                return null;
        }

        #endregion
    }
}
